package lk.icta.user.entity;

import javax.persistence.*;
import java.util.BitSet;

/**
 * Represents a Role defined in the system. A user may belong to one or more Roles  *
 *
 * @author Mahesha Kalpanie
 */
@Entity
@Table(schema = "USERS_RAIL")
public class Role {
    @Id
    @Column(updatable = false)
    private String id;

    @Column(nullable = false, columnDefinition = "smallint not null default 1")
    private int status;

    /**
     * Role name
     */
    @Column(nullable = false, unique = true)
    private String name;

    @Transient
    /** The permission BitSet used at runtime - loaded from the permissions byte[] */
    private BitSet permBitSet;

    /**
     * Used to persist the permission BitSet
     */
    @Lob
    @Column(length = 128)
    @Basic(fetch = FetchType.EAGER)
    private byte[] permissions;

    public Role() {
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Role role = (Role) o;
        if (id != null ? !id.equals(role.id) : role.id != null) return false;
        return true;
    }

    @Override
    public int hashCode() {
        return id != null ? id.hashCode() : 0;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public BitSet getPermBitSet() {
        return permBitSet;
    }

    public void setPermBitSet(BitSet permBitSet) {
        this.permBitSet = permBitSet;
        byte[] bytes = new byte[permBitSet.length() / 8 + 1];
        for (int i = 0; i < permBitSet.length(); i++) {
            if (permBitSet.get(i)) {
                bytes[bytes.length - i / 8 - 1] |= 1 << (i % 8);
            }
        }
        permissions = bytes;
    }

    public byte[] getPermissions() {
        return permissions;
    }

    public void setPermissions(byte[] permissions) {
        this.permissions = permissions;
        if (permissions != null) {
            for (int i = 0; i < permissions.length * 8; i++) {
                if ((permissions[permissions.length - i / 8 - 1] & (1 << (i % 8))) > 0) {
                    if (permBitSet == null) {
                        permBitSet = new BitSet();
                    }
                    permBitSet.set(i);
                }
            }
        }
    }

    @PostLoad
    private void init() {
        setPermissions(permissions);
    }
}